package mirrormonkey.framework.test.application;

import java.util.IdentityHashMap;
import java.util.Iterator;

import mirrormonkey.core.EntityLifecycleListener;
import mirrormonkey.core.server.ServerConnectionInfo;
import mirrormonkey.core.server.ServerCoreModule;
import mirrormonkey.core.server.ServerEntityData;
import mirrormonkey.framework.ConnectionInfo;
import mirrormonkey.framework.ServerSyncAppState;
import mirrormonkey.framework.entity.StaticEntityData;
import mirrormonkey.framework.entity.SyncEntity;

import com.jme3.network.HostedConnection;
import com.jme3.network.Network;
import com.jme3.network.Server;
import com.jme3.system.JmeContext;

public class ServerTestApplication extends TestApplication<ServerSyncAppState>
		implements EntityLifecycleListener {

	public final Server server;

	public final IdentityHashMap<SyncEntity, SyncEntity> allEntities;

	public final ServerCoreModule coreModule;

	public ServerTestApplication() throws Throwable {
		this(Network.createServer(PORT));
	}

	public ServerTestApplication(Server server) throws Throwable {
		super(new ServerSyncAppState(server));
		this.server = server;
		allEntities = new IdentityHashMap<SyncEntity, SyncEntity>();

		coreModule = appState.getModule(ServerCoreModule.class);
		coreModule.getListenerConfiguration().addListener(this);
		coreModule.getListenerConfiguration().addListener(generalListener);
	}

	@Override
	public void start() {
		server.start();
		start(JmeContext.Type.Headless);
	}

	@Override
	public void stop() {
		server.close();
		super.stop(true);
	}

	@Override
	public void clear() {
		while (!allEntities.isEmpty()) {
			Iterator<SyncEntity> i = allEntities.values().iterator();
			SyncEntity e = i.next();
			if (e.getData() != null) {
				((ServerEntityData) e.getData()).destroy();
			}
			i.remove();
		}
		for (HostedConnection i : server.getConnections()) {
			ServerConnectionInfo info = coreModule.getData(i);
			info.destroy();
		}
		super.clear();
	}

	@Override
	public void entityInitialized(SyncEntity entity,
			ConnectionInfo connectionInfo) {
		allEntities.put(entity, entity);
	}

	@Override
	public void entityReplaced(SyncEntity replacedEntity,
			StaticEntityData replacedStaticData, SyncEntity replacingEntity,
			ConnectionInfo connectionInfo) {
	}

	@Override
	public void entityReplacing(SyncEntity replacedEntity,
			StaticEntityData replacedStaticData, SyncEntity replacingEntity,
			ConnectionInfo connectionInfo) {
		allEntities.put(replacingEntity, replacingEntity);
	}

	@Override
	public void entityRemoved(SyncEntity entity, ConnectionInfo connectionInfo) {
	}

	@Override
	public int getSortingOrder() {
		return FRAMEWORK_MAX_SORTING_ORDER;
	}

}